﻿using Microsoft.EntityFrameworkCore;
using RotovapPlatform.Domain.Business.Recipes.Entities;
using System;
using System.IO;
using System.Diagnostics;
using System.Text.Json;
using System.Text.Encodings.Web;
using System.Text.Unicode;

namespace RotovapPlatform.Infrastructure.Common.Data
{
	/// <summary>
	/// 实验数据库上下文
	/// </summary>
	public class ExperimentDbContext : DbContext
	{
		/// <summary>
		/// 实验表
		/// </summary>
		public DbSet<Experiment> Experiments { get; set; }

		/// <summary>
		/// 配方表
		/// </summary>
		public DbSet<RecipeDefinition> Recipes { get; set; }

		/// <summary>
		/// 构造函数
		/// </summary>
		/// <param name="options">数据库上下文选项</param>
		public ExperimentDbContext(DbContextOptions<ExperimentDbContext> options)
			: base(options)
		{
			try
			{
				Database.EnsureCreated();
				Debug.WriteLine("ExperimentDbContext initialized");

				// 添加调试日志
				Debug.WriteLine($"ExperimentDbContext options: {options.ContextType}");
				//Debug.WriteLine($"ExperimentDbContext connection string: {options.FindExtension<Microsoft.EntityFrameworkCore.Infrastructure.CoreOptionsExtension>()?.ConnectionString}");
			}
			catch (Exception ex)
			{
				Debug.WriteLine($"Error initializing ExperimentDbContext: {ex.Message}");
				throw;
			}
		}

		/// <summary>
		/// 配置实体映射
		/// </summary>
		/// <param name="modelBuilder">模型构建器</param>
		protected override void OnModelCreating(ModelBuilder modelBuilder)
		{
			base.OnModelCreating(modelBuilder);

			// 配置Experiment实体
			modelBuilder.Entity<Experiment>(entity =>
			{
				entity.HasKey(e => e.ExperimentId);
				entity.Property(e => e.ExperimentId).ValueGeneratedNever();

				// 配置与RecipeDefinition的关系
				entity.HasOne(e => e.Recipe)
					  .WithMany()
					  .HasForeignKey(e => e.RecipeId)
					  .OnDelete(DeleteBehavior.Restrict)
					  .IsRequired(true);  // 确保RecipeId是必填的

				// 明确指示EF Core不要尝试级联保存Recipe实体
				entity.Navigation(e => e.Recipe).AutoInclude(false);

				// 配置可为null的字段
				entity.Property(e => e.ExecutionResult).IsRequired(false);
				entity.Property(e => e.ErrorMessage).IsRequired(false);
				entity.Property(e => e.Executor).IsRequired(false);

				// 配置ExecutionParameters为JSON字符串
				var jsonOptions = new JsonSerializerOptions
				{
					Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
					WriteIndented = true
				};

				entity.Property(e => e.ExecutionParameters)
					  .HasConversion(
						  v => JsonSerializer.Serialize(v, jsonOptions),
						  v => JsonSerializer.Deserialize<RotovapPlatform.Domain.Business.Recipes.Entities.Parameters.RotovapParameters>(v, jsonOptions)
					  );
			});

			// 配置RecipeDefinition实体
			modelBuilder.Entity<RecipeDefinition>(entity =>
			{
				entity.ToTable("Recipes", t => t.ExcludeFromMigrations());  // 排除Recipes表，因为它已经由RecipeDbContext创建
				entity.HasKey(e => e.RecipeId);
				entity.Property(e => e.RecipeId).ValueGeneratedNever();

				// 配置RotovapParameters为JSON字符串
				var jsonOptions = new JsonSerializerOptions
				{
					Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
					WriteIndented = true
				};

				entity.Property(e => e.RotovapParameters)
					  .HasConversion(
						  v => JsonSerializer.Serialize(v, jsonOptions),
						  v => JsonSerializer.Deserialize<RotovapPlatform.Domain.Business.Recipes.Entities.Parameters.RotovapParameters>(v, jsonOptions)
					  );

				// 明确指示 EF Core 不要尝试插入或更新 Recipe 实体
				entity.Metadata.SetIsTableExcludedFromMigrations(true);
			});

			// 忽略所有参数类型，它们应该作为JSON存储而不是单独的表
			modelBuilder.Ignore<RotovapPlatform.Domain.Business.Recipes.Entities.Parameters.ProductParameters>();
			modelBuilder.Ignore<RotovapPlatform.Domain.Business.Recipes.Entities.Parameters.ResidualLiquidParameters>();
			modelBuilder.Ignore<RotovapPlatform.Domain.Business.Recipes.Entities.Parameters.CleaningParameters>();
		}

		/// <summary>
		/// 配置数据库连接
		/// </summary>
		/// <param name="optionsBuilder">数据库配置构建器</param>
		protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
		{
			if (!optionsBuilder.IsConfigured)
			{
				var solutionDir = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..\\..\\..\\..\\.."));
				var infrastructureDir = Path.Combine(solutionDir, "src", "RotovapPlatform.Infrastructure");
				var folder = Path.Combine(infrastructureDir, "Data");

				if (!Directory.Exists(folder))
				{
					Directory.CreateDirectory(folder);
				}

				var dbPath = Path.Combine(folder, "Rotovap.db");
				optionsBuilder.UseSqlite($"Data Source={dbPath}");
			}
		}
	}
}
